package cn.iocoder.yudao.module.forward.service.datasourceregisterconfig;

import cn.iocoder.yudao.module.forward.controller.admin.datasourceinfo.vo.DataSourceInfoSaveReqVO;
import cn.iocoder.yudao.module.forward.dal.dataobject.datasourceinfo.DataSourceInfoDO;
import cn.iocoder.yudao.module.forward.enums.DfsErrorCodeConstants;
import cn.iocoder.yudao.module.forward.http.register.RegisterUtil;
import cn.iocoder.yudao.module.forward.http.register.model.*;
import cn.iocoder.yudao.module.forward.mqtt.MqttConstants;
import cn.iocoder.yudao.module.forward.service.datasourceinfo.DataSourceInfoService;
import com.alibaba.druid.util.StringUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;

import org.springframework.validation.annotation.Validated;

import cn.iocoder.yudao.module.forward.controller.admin.datasourceregisterconfig.vo.*;
import cn.iocoder.yudao.module.forward.dal.dataobject.datasourceregisterconfig.DataSourceRegisterConfigDO;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;

import cn.iocoder.yudao.module.forward.dal.mysql.datasourceregisterconfig.DataSourceRegisterConfigMapper;

import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;

/**
 * 信息源注册配置信息 Service 实现类
 *
 * @author dfs
 */
@Slf4j
@Service
@Validated
public class DataSourceRegisterConfigServiceImpl implements DataSourceRegisterConfigService {

    @Resource
    private DataSourceRegisterConfigMapper dataSourceRegisterConfigMapper;
    //    @Resource
//    private DataSourceInfoMapper dataSourceInfoMapper;
    @Resource
    private DataSourceInfoService dataSourceInfoService;

    @Override
    public Integer createDataSourceRegisterConfig(DataSourceRegisterConfigSaveReqVO createReqVO) {
        // 插入
        DataSourceRegisterConfigDO dataSourceRegisterConfig = BeanUtils.toBean(createReqVO, DataSourceRegisterConfigDO.class);
        dataSourceRegisterConfigMapper.insert(dataSourceRegisterConfig);
        registerAndAuth(dataSourceRegisterConfig);
        // 返回
        return dataSourceRegisterConfig.getId();
    }

    @Override
    public void updateDataSourceRegisterConfig(DataSourceRegisterConfigSaveReqVO updateReqVO) {
        // 校验存在
        validateDataSourceRegisterConfigExists(updateReqVO.getId());
        // 更新
        DataSourceRegisterConfigDO updateObj = BeanUtils.toBean(updateReqVO, DataSourceRegisterConfigDO.class);
        dataSourceRegisterConfigMapper.updateById(updateObj);
        registerAndAuth(updateObj);
    }

    @Override
    public void deleteDataSourceRegisterConfig(Integer id) {
        // 校验存在
        validateDataSourceRegisterConfigExists(id);
        // 删除
        dataSourceRegisterConfigMapper.deleteById(id);
    }

    private void validateDataSourceRegisterConfigExists(Integer id) {
        if (dataSourceRegisterConfigMapper.selectById(id) == null) {
            throw exception(DfsErrorCodeConstants.DATA_SOURCE_REGISTER_CONFIG_NOT_EXISTS);
        }
    }

    @Override
    public DataSourceRegisterConfigDO getDataSourceRegisterConfig(Integer id) {
        return dataSourceRegisterConfigMapper.selectById(id);
    }

    @Override
    public PageResult<DataSourceRegisterConfigDO> getDataSourceRegisterConfigPage(DataSourceRegisterConfigPageReqVO pageReqVO) {
        return dataSourceRegisterConfigMapper.selectPage(pageReqVO);
    }

    @Override
    public DataSourceRegisterConfigDO getDataSourceRegisterConfigBySourceId(Integer sourceId) {
        try {
            return dataSourceRegisterConfigMapper.selectOne(DataSourceRegisterConfigDO::getSourceId, sourceId);
        } catch (Exception e) {
            return null;
        }
    }

    private void registerAndAuth(DataSourceRegisterConfigDO dataSourceRegisterConfig) {
        if (dataSourceRegisterConfig == null) {
            log.error("dataSourceRegisterConfig == null");
            return;
        }
        DataSourceInfoDO dataSourceInfoDO = dataSourceInfoService.getDataSourceInfoBySourceId(dataSourceRegisterConfig.getSourceId());

        if (dataSourceInfoDO == null) {
            dataSourceInfoDO = new DataSourceInfoDO();
            dataSourceInfoDO.setSourceId(dataSourceRegisterConfig.getSourceId());
        }

        //注册
        dataSourceInfoDO = register(dataSourceInfoDO, dataSourceRegisterConfig);
        //授权
        dataSourceInfoDO = auth(dataSourceInfoDO, dataSourceRegisterConfig);

        DataSourceInfoSaveReqVO saveReqVO = BeanUtils.toBean(dataSourceInfoDO, DataSourceInfoSaveReqVO.class);
        if (saveReqVO.getId() == null) {
            dataSourceInfoService.createDataSourceInfo(saveReqVO);
        } else {
            dataSourceInfoService.updateDataSourceInfo(saveReqVO);
        }
    }

    private DataSourceInfoDO register(DataSourceInfoDO dataSourceInfoDO, DataSourceRegisterConfigDO dataSourceRegisterConfig) {
        RegisterInfo registerInfo = new RegisterInfo(
                dataSourceRegisterConfig.getLicense(),
                dataSourceRegisterConfig.getOwner(),
                dataSourceRegisterConfig.getType());
        RegisterResp registerResult = RegisterUtil.register(dataSourceRegisterConfig.getAddress(), registerInfo);
        if (registerResult != null) {
            dataSourceInfoDO.setGroupId(registerResult.getResult().getGroupId());
            dataSourceInfoDO.setClientId(registerResult.getResult().getClientId());
            dataSourceInfoDO.setUsername(registerResult.getResult().getUname());
            dataSourceInfoDO.setPwd(registerResult.getResult().getPwd());
        }

        if (StringUtils.isEmpty(dataSourceInfoDO.getGroupId()) ||
                StringUtils.isEmpty(dataSourceInfoDO.getClientId()) ||
                StringUtils.isEmpty(dataSourceInfoDO.getUsername()) ||
                StringUtils.isEmpty(dataSourceInfoDO.getPwd())) {
            throw exception(DfsErrorCodeConstants.DATA_SOURCE_REGISTER);
        }

        return dataSourceInfoDO;
    }

    private DataSourceInfoDO auth(DataSourceInfoDO dataSourceInfoDO, DataSourceRegisterConfigDO dataSourceRegisterConfig) {
        Authorize authorize = new Authorize();
        authorize.setScope(dataSourceRegisterConfig.getScope());
        authorize.setClientId(dataSourceInfoDO.getClientId());
        authorize.setUname(dataSourceInfoDO.getUsername());
        authorize.setPwd(dataSourceInfoDO.getPwd());
        AuthorizeResp authorizeResult = RegisterUtil.auth(dataSourceRegisterConfig.getAddress(), authorize);
        try {
            for (AuthorizeResult result : authorizeResult.getResult()) {
                dataSourceInfoDO.setIp(result.getMqtthost());
                dataSourceInfoDO.setPort(result.getPort());
                if (result.getScope().toLowerCase().contains(MqttConstants.TOPIC_TYPE_EEW)) {
                    dataSourceInfoDO.setTopicEew(result.getTopic());
                } else if (result.getScope().toLowerCase().contains(MqttConstants.TOPIC_TYPE_EQR)) {
                    dataSourceInfoDO.setTopicEqr(result.getTopic());
                } else if (result.getScope().toLowerCase().contains(MqttConstants.TOPIC_TYPE_ACK)) {
                    dataSourceInfoDO.setTopicAckFirst(result.getTopic());
                }
            }
        } catch (Exception e) {
            DataSourceInfoSaveReqVO saveReqVO = BeanUtils.toBean(dataSourceInfoDO, DataSourceInfoSaveReqVO.class);
            if (saveReqVO.getId() == null) {
                dataSourceInfoService.createDataSourceInfo(saveReqVO);
            } else {
                dataSourceInfoService.updateDataSourceInfo(saveReqVO);
            }
            throw exception(DfsErrorCodeConstants.DATA_SOURCE_AUTH);
        }
        return dataSourceInfoDO;
    }
}